<?php
/**
 * Created by PhpStorm.
 * FileName: Appointment.class.php
 * User: Administrator
 * Date: 2018/4/16
 * Time: 10:02
 */

namespace Api\Controller;

use Admin\Model\AirwayDetailModel;
use Admin\Model\AirwayModel;
use Admin\Model\OrderModel;
use Admin\Model\TripFavoriteModel;
use Admin\Model\TripModel;

class TripController extends ApiController {

    private $tripModel;
    private $airwayModel;
    private $airwayDetailModel;
    private $tripFavoriteModel;
    private $stateList;
    private $orderModel;

    public function __construct() {
        parent::__construct();
        $this->tripModel = new TripModel();
        $this->airwayModel = new AirwayModel();
        $this->airwayDetailModel = new AirwayDetailModel();
        $this->tripFavoriteModel = new TripFavoriteModel();
        $this->orderModel = new OrderModel();

        // 行程状态标签、描述及该状态下可执行的操作
        $this->stateList = array(
            '0' => array('label' => '审核中','desc' => '发布请求已提交，审核中',
                'action' => array(array('type' => 'close')), // 关闭
            ),
            '1' => array('label' => '接单中','desc' => '审核通过、正在接单',
                'action' => array(array('type' => 'pause'),array('type' => 'close')), // 暂停接单，关闭
            ),
            '2' => array('label' => '订单已满','desc' => '订单数量达到上限，无法继续接单',
                'action' => array(array('type' => 'close')), // 关闭
            ),
            '3' => array('label' => '接单结束','desc' => '您的行程已经结束、无法继续接单',
                'action' => array(array('type' => 'close')), // 关闭
            ),
            '4' => array('label' => '已暂停接单','desc' => '您已暂停接单',
                'action' => array(array('type' => 'recover'),array('type' => 'close')), // 恢复接单，关闭
            ),
            '5' => array('label' => '已关闭','desc' => '行程已关闭',
                'action' => array(array('type' => 'delete')) // 删除
            ),
        );
    }

    // 行程检索
    public function index() {
        $order = $this->buildOrder();
        $pageSize = 15;
        $curPage = I('p',1);
        $firstRow  = $pageSize * ($curPage - 1);
        $tripIds = $this->getTripIdsByAir();
        // 只返回审核通过且接单中的行程
        $sql = 'select t.id as trip_id,t.ticket_id,t.user_id,t.real_name,t.reward_min,t.contact,t.contact_type,t.lng,t.lat,t.origin,t.destination,t.depart_date,t.reach_date,u.user_name,u.gender,u.avatar,u.credit from trip t,users u where t.user_id=u.id and t.status=1 and t.state=1 ';
        if ($tripIds) {
            $tripAir = $this->getAirByTrip($tripIds);
            if ($tripAir) {
                $sql .= ' and t.id in ('.implode(',',$tripIds).')';
            } else {
                $sql .= ' and t.id in (0)';
            }
        } else {
            $sql .= ' and t.id in (0)';
        }
        // 排除指定规则的行程
        $exceptTrip = $this->exceptTrip();
        if ($exceptTrip) {
            $sql .= ' and t.id not in ('.implode(',',$exceptTrip).')';
        }
//        // 如果指定了出发地，则行程出发时间必须大于当前时间
//        if (I('origin')) {
//            $sql .= ' and t.depart_date>unix_timestamp()';
//        }
        $sql .= ' order by '.$order;
        $sql .= ' limit '.$firstRow.','.$pageSize;
        $list = M()->query($sql);
        $calculateDeposit = $this->calculateDeposit($tripIds);
        foreach ($list as $key => $item) {
            $list[$key]['airway'] = $tripAir[$item['trip_id']];
            $contact = json_decode($item['contact'],true);
            $list[$key]['contact'] = $contact;
            // 预付款剩余额度
            $list[$key]['surplus_money'] = $calculateDeposit[$item['trip_id']];
        }
        $data['list'] = $list;
        $data['nowPage'] = $curPage;
        $data['pageSize'] = $pageSize;
        return $this->callBack("行程列表",$this->SUCCESS_CODE,$data);
    }

    // 我的行程列表 - 进行中
    public function myList() {
        $where = array();
        $user_id = I('user_id');
        if (!$user_id) {
            $this->callBack('无效的参数',$this->ERROR_CODE);
        }
        $where['user_id'] = $user_id;
        $where['state'] = array('lt',5);
        $pageSize = 15;
        $curPage = I('p',1);
        $data = $this->tripModel->getList($where,$pageSize,$curPage);
        $list = $data['list'];
        foreach ($list as $key => $item) {
            $list[$key]['state_text'] = $this->stateList[$item['state']]['label'];
            $list[$key]['state_desc'] = $this->stateList[$item['state']]['desc'];
            $list[$key]['action'] = $this->stateList[$item['state']]['action'];
        }
        $data['list'] = $list;
        return $this->callBack("行程列表",$this->SUCCESS_CODE,$data);
    }

    // 我的行程列表 - 已关闭
    public function myListEnd() {
        $where = array();
        $user_id = I('user_id');
        if (!$user_id) {
            $this->callBack('无效的参数',$this->ERROR_CODE);
        }
        $where['user_id'] = $user_id;
        $where['state'] = 5;
        $pageSize = 15;
        $curPage = I('p',1);
        $data = $this->tripModel->getList($where,$pageSize,$curPage);
        $list = $data['list'];
        $tripIds = array();
        foreach ($list as $item) {
            $tripIds[] = $item['id'];
        }
        $tripOrders = $this->getTripOrders($tripIds);
        foreach ($list as $key => $item) {
            $list[$key]['state_text'] = $this->stateList[$item['state']]['label'];
            $list[$key]['state_desc'] = $item['status'] == '2' ? sprintf('审核不通过，可能原因是%s，如有疑问请联系客服',$item['remark']) : $this->stateList[$item['state']]['desc'];
            $list[$key]['action'] = $this->stateList[$item['state']]['action'];
            $list[$key]['reward'] = $tripOrders[$item['id']]['reward'];
            $list[$key]['done'] = $tripOrders[$item['id']]['done'];
            $list[$key]['cancel'] = $tripOrders[$item['id']]['cancel'];
            $list[$key]['fail'] = $tripOrders[$item['id']]['fail'];
        }
        $data['list'] = $list;
        return $this->callBack("行程列表",$this->SUCCESS_CODE,$data);
    }

    // 行程明细
    public function detail() {
        $id = I('id');
        $user_id = I('user_id');
        if (!$id) {
            $this->callBack('无效的参数',$this->ERROR_CODE);
        }
        $data = $this->tripModel->detail(array('id' => $id));
        $contact = array();
        if ($data['contact']['tel']) {
            $contact[] = array('type' => 'tel', 'value' => $data['contact']['tel']);
        }
        if ($data['contact']['wx']) {
            $contact[] = array('type' => 'wx', 'value' => $data['contact']['wx']);
        }
        $data['contact'] = $contact;
        $data['state_text'] = $this->stateList[$data['state']];
        $tripFavorite = $this->tripFavoriteModel->where(array('user_id' => $user_id))->getField('trip_id',true);
        $data['isFavorited'] = in_array($data['id'],$tripFavorite) ? true : false;
        $calculateDeposit = $this->calculateDeposit($id);
        // 预付款剩余额度
        $data['surplus_money'] = $calculateDeposit[$id];
        // 查询客户是否已获取过联系方式
        $data['is_contacted'] = $this->checkIsContacted($id,$user_id);
        // 获取联系需要支付的费用
        $money_gain_contact = $this->sysConfig['money_gain_contact'];
        $data['money_gain_contact'] = $money_gain_contact ? $money_gain_contact : 0;
        $data['action'] = $this->stateList[$data['state']]['action'];
        return $this->callBack("行程明细",$this->SUCCESS_CODE,$data);
    }

    // 发布行程
    public function add() {
        $data = array();
        $user_id = I('user_id');
        $ticket_id = I('ticket_id');
        $real_name = I('real_name');
        $reward_min = I('reward_min');
        $description = I('description');
        $contact = I('contact');
        $lng = I('lng',0);
        $lat = I('lat',0);
        //$contact_type = I('contact_type');
        if (!$user_id || !$ticket_id || !$real_name || !$contact) {
            $this->callBack('无效的参数',$this->ERROR_CODE);
        }
        if ($this->getTripsByMonth($user_id) >= $this->sysConfig['month_trips_max']) {
            return $this->callBack('您当月已发布行程的次数已达上限！',$this->ERROR_CODE);
        }

        if ($this->checkTicketId($ticket_id)) {
            return $this->callBack('该客票号已存在，请勿重复发布！',$this->ERROR_CODE);
        }

        $contacts = array();
        $contact_tmp = explode('|',$contact);
        foreach ($contact_tmp as $tmps) {
            $item = explode(':',$tmps);
            if (!trim($item[1])) {
                continue;
            }
            $contacts[trim($item[0])] = trim($item[1]);
        }
        if (!$contacts) {
            $this->callBack('无效的参数',$this->ERROR_CODE);
        }
        $data = array(
            'user_id' => $user_id,
            'ticket_id' => $ticket_id,
            'real_name' => $real_name,
            'reward_min' => $reward_min,
            'description' => $description,
            'lng' => $lng,
            'lat' => $lat,
            'contact' => json_encode($contacts,JSON_UNESCAPED_UNICODE)
            //'contact_type' => $contact_type
        );
        $rs = $this->tripModel->add($data);
        if ($rs !== false) {
            return $this->callBack("行程添加成功！",$this->SUCCESS_CODE);
        }
        return $this->callBack("行程添加失败！",$this->ERROR_CODE);
    }

    // 行程状态变更
    public function changeStatus() {
        $id = I('id');
        $state = I('state');
        if (!$id || !$state) {
            $this->callBack('无效的参数',$this->ERROR_CODE);
        }
        if ($state == '5') {
            if ($this->checkProcessingOrder($id)) {
                return $this->callBack('该行程有执行中的订单，无法关闭！',$this->ERROR_CODE);
            }
        }
        $rs = $this->tripModel->update(array('state' => $state),array('id' => $id));
        if ($rs !== false) {
            return $this->callBack('行程状态变更成功！',$this->SUCCESS_CODE);
        }
        return $this->callBack('行程状态变更失败！',$this->ERROR_CODE);
    }

    // 删除行程
    public function delete() {
        $id = I('id');
        if (!$id) {
            $this->callBack('无效的参数',$this->ERROR_CODE);
        }
        $rs = $this->tripModel->update(array('state' => 6),array('id' => $id));
        if ($rs !== false) {
            return $this->callBack("行程删除成功！",$this->SUCCESS_CODE);
        }
        return $this->callBack("行程删除失败！",$this->ERROR_CODE);
    }

    // 构造检索条件
    private function buildCondition() {
        $where = '';
        $air_code = I('air_code');
        $origin = I('origin');
        $destination = I('destination');
        $depart_date = I('depart_date');
        $reach_date = I('reach_date');
        $date_type = I('data_type');
        if (!$depart_date) {
            die($this->callBack('出发日期不能为空！',$this->ERROR_CODE));
        }
        // 航班号
        if ($air_code) {
            $where .= sprintf(" and air_code='%s'", $air_code);
        }
        // 航段
        $station = '';
        if ($origin) {
            $station = sprintf(" and find_in_set('%s',station)",$origin);
        }
        if ($destination) {
            $station .= sprintf(" and find_in_set('%s',station)",$destination);
        }
        if ($origin && $destination) {
            $station .= sprintf(" and (locate('%s',station)<locate('%s',station) or locate('%s',station_rev)<locate('%s',station_rev))",$origin,$destination,$origin,$destination);
        }
        $tripIds = array();
        if ($station) {
            $preTripSql = sprintf("select id from `trip` where status=1 %s",$station);
            $preTrip = M()->query($preTripSql);
            foreach ($preTrip as $item) {
                $tripIds[] = $item['id'];
            }
        }
        if ($origin || $destination) {
            if ($tripIds) {
                $where .= sprintf(" and trip_id in (%s)", implode(',',$tripIds));
            } else {
                $where .= sprintf(" and trip_id in (%s)", 0);
            }
        }
        switch ($date_type) {
            case '1':
                // 到达时间
                if ($depart_date) {
                    $where .= sprintf(" and reach_date >= %s", strtotime($depart_date));
                }
                if ($reach_date) {
                    $where .= sprintf(" and reach_date <= %s", strtotime($reach_date.' 23:59:59'));
                }
                break;
            case '2':
                // 出发时间
                if ($depart_date) {
                    $where .= sprintf(" and depart_date >= %s", strtotime($depart_date));
                }
                if ($reach_date) {
                    $where .= sprintf(" and depart_date <= %s", strtotime($reach_date.' 23:59:59'));
                }
                break;
            case '3':
                // 出发+到达时间
                if ($depart_date) {
                    $where .= sprintf(" and from_unixtime(depart_date,'%%Y-%%m-%%d')='%s'", $depart_date);
                }
                if ($reach_date) {
                    $where .= sprintf(" and from_unixtime(reach_date,'%%Y-%%m-%%d')='%s'", $reach_date);
                }
                break;
        }
        return $where;
    }

    // 航段检索条件
    private function buildAirwayCondition() {
        $where = '';
        $air_code = I('air_code');
        $origin = I('origin');
        $destination = I('destination');
        $depart_date = I('depart_date');
        $reach_date = I('reach_date');
        $date_type = I('data_type');
        if (!$depart_date) {
            die($this->callBack('出发日期不能为空！',$this->ERROR_CODE));
        }
        // 航班号
        if ($air_code) {
            $where .= sprintf(" and air_code='%s'", $air_code);
        }
        // 航段
        if ($origin && $destination) {
            $where .= sprintf(" and (origin='%s' or destination='%s')",$origin,$destination);
            // 如果指定了出发地，则行程出发时间必须大于当前时间
            $where .= ' and depart_date>unix_timestamp()';
        } else if ($origin) {
            $where .= sprintf(" and origin='%s'",$origin);
            // 如果指定了出发地，则行程出发时间必须大于当前时间
            $where .= ' and depart_date>unix_timestamp()';
        } else if ($destination) {
            $where .= sprintf(" and destination='%s'",$destination);
        }
        switch ($date_type) {
            case '1':
                // 到达时间
                if ($depart_date) {
                    $where .= sprintf(" and reach_date >= %s", strtotime($depart_date));
                }
                if ($reach_date) {
                    $where .= sprintf(" and reach_date <= %s", strtotime($reach_date.' 23:59:59'));
                }
                break;
            case '2':
                // 出发时间
                if ($depart_date) {
                    $where .= sprintf(" and depart_date >= %s", strtotime($depart_date));
                }
                if ($reach_date) {
                    $where .= sprintf(" and depart_date <= %s", strtotime($reach_date.' 23:59:59'));
                }
                break;
            case '3':
                // 出发+到达时间
                if ($depart_date) {
                    $where .= sprintf(" and from_unixtime(depart_date,'%%Y-%%m-%%d')='%s'", $depart_date);
                }
                if ($reach_date) {
                    $where .= sprintf(" and from_unixtime(reach_date,'%%Y-%%m-%%d')='%s'", $reach_date);
                }
                break;
        }
        return $where;
    }

    // 构造排序条件
    private function buildOrder() {
        $order = '';
        $sort = I('sort');
        if ($sort) {
            // 航段
            $order = 'station_num asc';
            // 转机次数
            $origin = I('origin');
            $destination = I('destination');
            if ($origin && $destination) {
                $order .= sprintf(",length(substring(station,locate('%s',station)+char_length('%s'),locate('%s',station)-locate('%s',station)-2))-length(replace(substring(station,locate('%s',station)+char_length('%s'),locate('%s',station)-locate('%s',station)-2),',','')) asc",$origin,$origin,$destination,$origin, $origin,$origin,$destination,$origin);
            }
        }
        switch ($sort) {
            case 'reach_date':
                $order .= ',reach_date asc';
                break;
            case 'reward_min':
                $order .= ',reward_min asc';
                break;
            case 'credit':
                $order .= ',credit desc';
                break;
            case 'dist':
                $lng = I('lng',0);
                $lat = I('lat',0);
                $order .= sprintf(',get_distance(%s,lng,%s,lat) asc',$lng,$lat);
                break;
            default:
                $order .= ',reach_date asc';
                break;
        }
        return $order;
    }

    // 根据条件从航班中查询出行程id
    private function getTripIdsByAir() {
        $where = $this->buildCondition();
        $airwaySql = 'select trip_id from airway where 1=1 ';
        $airwaySql .= $where;
        $airwayList = M()->query($airwaySql);
        $tripIds = array();
        foreach ($airwayList as $airwayItem) {
            $tripIds[] = $airwayItem['trip_id'];
        }
        return $tripIds;
    }

    // 根据行程id查询出航班信息
    private function getAirByTrip($tripIds) {
        $airwaySql = 'select id,trip_id,air_code,origin,destination,depart_date,reach_date from airway where trip_id in ('.implode(',',$tripIds).') ';
        $airwaySql .= $this->buildAirwayCondition();
        $airwayList = M()->query($airwaySql);
        $tripAir = array();
        foreach ($airwayList as $airwayItem) {
            $tripAir[$airwayItem['trip_id']][] = $airwayItem;
        }
        return $tripAir;
    }

    // 计算预付款剩余额度
    private function calculateDeposit($tripIds) {
        $reward_min = $this->sysConfig['reward_min'];
        $data = array();
        if (!$tripIds) {
            return $data;
        }
        $tripIds = is_array($tripIds) ? $tripIds : array($tripIds);
        foreach ($tripIds as $tripId) {
            $data[$tripId] = $reward_min;
        }
        $sql = 'select trip_id,sum(deposit) as deposit from `order` where trip_id in ('.implode(',',$tripIds).') and  state in (1,2,3,8) group by trip_id';
        $result = M()->query($sql);
        foreach ($result as $item) {
            $data[$item['trip_id']] = $item['deposit']>$reward_min ? 0 : $reward_min - $item['deposit'];
        }
        return $data;
    }

    // 行程订单统计
    private function getTripOrders($tripIds) {
        $data = array();
        if (!$tripIds) {
            return $data;
        }
        foreach ($tripIds as $tripId) {
            $data[$tripId]['reward'] = 0;
            $data[$tripId]['done'] = 0;
            $data[$tripId]['cancel'] = 0;
            $data[$tripId]['fail'] = 0;
        }
        $rewardSql = 'select trip_id,ifnull(sum(ifnull(reward,0)),0) as total from `order` where trip_id in ('.implode(',',$tripIds).') group by trip_id';
        $result = M()->query($rewardSql);
        foreach ($result as $item) {
            $data[$item['trip_id']]['reward'] = $item['total'];
        }
        $sql = 'select trip_id,state,count(1) as total from `order` where trip_id in ('.implode(',',$tripIds).') and state in (5,6,8) group by trip_id,state';
        $result = M()->query($sql);
        $stateLabel = array('5' => 'cancel','6' => 'fail','8' => 'done');
        foreach ($result as $item) {
            $data[$item['trip_id']][$stateLabel[$item['state']]] = $item['total'];
        }
        return $data;
    }

    // 获取当月已发布的行程次数
    private function getTripsByMonth($user_id) {
        $where = array(
            'user_id' => $user_id,
        );
        $tripCount = $this->tripModel->where($where)->where("from_unixtime(add_time,'%Y%m')=date_format(now(),'%Y%m')")->count();
        return $tripCount;
    }

    // 查询客户是否已获取过联系方式
    private function checkIsContacted($id,$user_id) {
        $where = array('trip_id' => $id,'buyer_id' => $user_id);
        $count = $this->orderModel->where($where)->count();
        return $count>0 ? true : false;
    }

    // 查询客票号是否存在
    private function checkTicketId($ticket_id){
        $where = array(
            'ticket_id' => $ticket_id
        );
        $count = $this->tripModel->where($where)->count();
        return $count>0 ? true : false;
    }

    // 检查某行程是否有正在进行的订单
    private function checkProcessingOrder($tripId) {
        $where = array(
            'trip_id' => $tripId,
            'state' => array('in',array('0','1','2'))
        );
        $count = $this->orderModel->where($where)->count();
        return $count>0 ? true : false;
    }

    // 排除三次未接单和接单后取消的行程
    private function exceptTrip() {
        $trip = array();
        $sql = 'select count(1) as num,trip_id from `order` where state=0 group by trip_id having count(1) > 2 ';
        $sql .= 'union ';
        $sql .= 'select count(1) as num_5,trip_id from `order` where state=5 group by trip_id having count(1) > 0';
        $res = M()->query($sql);
        if ($res) {
            foreach ($res as $item) {
                $trip[] = $item['trip_id'];
            }
        }
        return $trip;
    }

}